"""
"""
import unittest as ut

import basicVdsTest as vdst
import vdsClient as vdsc
from storageConnectionTestUtils import eStorageType, disconnectFromStorage, connectToStorage, validateConnections, CONNECTIONS_OPTION_DEFAULT
from storageDomainTestUtils import eDomainClass, generateDomainTargets, destroyDomainTargets
from confUtils import Validate
from vdsClient import BLANK_UUID
from agentUtils import connectAgent
from testUtils import retry

class LVExtendSequence(vdst.BasicVDSTest):
    #For convenience. I didn't put it in the base class because I didn't want to commit.
    mycfg = property(lambda self: self.cfg[self.__class__.__name__])
    @classmethod
    def getConfigTemplate(cls):
        return { cls.__name__ : {
                        "VdsUri1" : {"default" : "http://server:54321"},
                        "VdsUri2" : {"default" : "http://server:54321"},
                        "Connections" : {"default" : CONNECTIONS_OPTION_DEFAULT, "validator" : validateConnections},
                        "Domain1" : {"default" : "GUID, GUID", "validator" : Validate.list},
                        "StorageType1": {"default" : "nfs", "validator" : eStorageType.parse},
                        "DomainClass1" : {"default" : "data", "validator" : eDomainClass.parse},
                        "HostID1" : {"default" : 7, "validator" : Validate.int},
                        "HostID2" : {"default" : 7, "validator" : Validate.int},
                        "Pool1Key" : {"default" : "NFSKEY"}
                    }
                }

    def setUp(self):
        #Setup clients
        self.client1 = vdsc.VDSClient()
        self.client1.setURI(self.mycfg["VdsUri1"])

        self.client2 = vdsc.VDSClient()
        self.client2.setURI(self.mycfg["VdsUri2"])
        self.agent2 = connectAgent(self.mycfg["VdsUri2"])

        #Make sure env is clean
        resp = self.assertVdscOK(self.client1.getConnectedStoragePoolsList())
        self.assertTrue(len(resp['poollist']) == 0, "VDSM 1 is connected to a pool. Dirty env. Bailing out.")

        resp = self.assertVdscOK(self.client2.getConnectedStoragePoolsList())
        self.assertTrue(len(resp['poollist']) == 0, "VDSM 2 is connected to a pool. Dirty env. Bailing out.")

        #Handle storage configuration
        connectToStorage(self.client1, self.mycfg["Connections"])
        connectToStorage(self.client2, self.mycfg["Connections"])
        self.domainTarget1 = generateDomainTargets(self.client1, self.mycfg["Connections"], [self.mycfg["Domain1"]])[0]

        #Create the tmp domain
        self.sdUUID = vdsc.VDSClient.newUUID()
        self.assertVdscOK(
            self.client1.createStorageDomain(self.mycfg["StorageType1"], self.sdUUID,
                "Storage Domain 1", self.domainTarget1, self.mycfg["DomainClass1"]
            )
        )

        #Create tmp pool
        self.spUUID = vdsc.VDSClient.newUUID()
        self.assertVdscOK(
            self.client1.createStoragePool(self.spUUID, "Swimming Pool", self.sdUUID, [self.sdUUID], 1)
            )

        self.assertVdscOK(
            self.client1.connectStoragePool(self.spUUID, self.mycfg["HostID1"], self.mycfg["Pool1Key"])
            )

        self.imgUUID = vdsc.VDSClient.newUUID()
        self.volUUID = vdsc.VDSClient.newUUID()

        #Start SPM on client 1
        taskid = self.assertVdscOK(self.client1.spmStart(self.spUUID, -1, -1, -1, False))['uuid']
        self.assertVdscTaskOK(self.client1, taskid)

        self.assertVdscOK(
            self.client1.activateStorageDomain(self.sdUUID, self.spUUID)
        )

        #Create volume
        volsize = 5120

        taskID = self.assertVdscOK(
            self.client1.createVolume(self.sdUUID, self.spUUID, self.imgUUID, volsize,
            vdsc.COW_FORMAT, vdsc.SPARSE_VOL, "DATA", self.volUUID, "Nietzsche", blocked = False)
        )['uuid']
        self.assertVdscTaskOK(self.client1, taskID)

        self.assertVdscOK(
            self.client2.connectStoragePool(self.spUUID, self.mycfg["HostID2"], self.mycfg["Pool1Key"])
            )

        self.vmUUID = vdsc.VDSClient.newUUID()

    def test(self):
        volDict = {"domainID" : self.sdUUID,
                   "poolID" : self.spUUID,
                   "volumeID" : self.volUUID,
                   "imageID" : self.imgUUID,
                   "if" : "IDE",
                   "index" : 0
                  }

        oldSize = int(self.assertVdscOK(
            self.client1.getVolumeInfo(self.sdUUID, self.spUUID,
                self.imgUUID, self.volUUID))['info']['truesize'])

        drives = [volDict]
        self.assertVdscOK(
            self.client2.create({'vmId' : self.vmUUID, 'memSize' : 256,
                'macAddr' : 'aa:bb:cc:dd:ee:ff', 'display' : 'vnc', 'drives' : drives})
            )
        # Try to send. It might take some time for the Fake VM to
        # open the communication port
        retry(lambda : self.agent2.makeFakeVMRaiseWatermarkReached(self.vmUUID, 'ide0-hd0'), 20)


        def checkVolume():
            newSize = int(self.assertVdscOK(
                self.client1.getVolumeInfo(self.sdUUID, self.spUUID,
                    self.imgUUID, self.volUUID))['info']['truesize'])

            self.assertTrue(newSize > oldSize)

        retry(checkVolume, 60)

    def tearDown(self):
        self.assertVdscOK(
            self.client2.destroy(self.vmUUID)
        )

        #Destroy pool
        self.assertVdscOK(
            self.client2.disconnectStoragePool(self.spUUID, self.mycfg["HostID1"], self.mycfg["Pool1Key"])
        )

        self.assertVdscOK(
            self.client1.deactivateStorageDomain(self.sdUUID, self.spUUID, BLANK_UUID, -1)
        )

        self.assertVdscOK(self.client1.destroyStoragePool(self.spUUID, self.mycfg["HostID1"], self.mycfg["Pool1Key"]))

        #format domain
        self.assertVdscOK(self.client1.formatStorageDomain(self.sdUUID))

        #disconnect
        destroyDomainTargets(self.client2, [self.domainTarget1])
        disconnectFromStorage(self.client1, self.mycfg["Connections"])
        disconnectFromStorage(self.client2, self.mycfg["Connections"])

def suite():
    tests = {
        LVExtendSequence : ["test"]
    }

    resSuite = ut.TestSuite()
    for testcase, methods in tests.iteritems():
        resSuite.addTests(map(testcase, methods))

    return resSuite

validateConfig = lambda cfg : vdst.validateSuiteConfig(suite(), cfg)
